

#include "memory.h"

#define EFLAGS_AC_BIT		0x00040000   //486的第18位是AC ，386没有
#define CR0_CACHE_DISABLE	0x60000000

//int  memtest_search (unsigned int start ,unsigned int end );
extern unsigned int memtest_search (unsigned int start ,unsigned int end ) ;

unsigned int  memtest (unsigned int start ,unsigned int end ) {  //返回最后的地址

	char flg486 =0 ; 
	unsigned int eflag ,cr0  ,i; 
	eflag =  io_load_eflags () ;
	eflag |=  EFLAGS_AC_BIT ; //我们把第18位置为1，如果存回去以后再读出来是0，则表示386
	io_store_eflags(eflag);
	eflag = io_load_eflags () ;
	if ((eflag & EFLAGS_AC_BIT )!=0) {  //表示486
		flg486 = 1 ;
	}

	if (flg486) { 
		cr0 = io_load_cr0 ();
		cr0 |=CR0_CACHE_DISABLE ;
		io_store_cr0(cr0) ;
	}
	i = memtest_search (start ,end);
	if (flg486) { 
		cr0 = io_load_cr0() ;
		cr0 &= ~CR0_CACHE_DISABLE ; //把CPU缓存重新开启
		io_store_cr0(cr0);
	}
	return i ;
}

/**内存管理初始化*/
void memman_init (MEMORY_MANAGEMENT *man) { 
	man->frees =  1 ;
	man->freem[0].addr = MEMORY_START ;
	man->freem[0].size = memtest(0x100000 ,0xffffffff) -MEMORY_START;
	man->maxfrees = 0 ;
	man ->lostsize = 0 ;
	man->losts = 0;
}
unsigned int memman_free_total (MEMORY_MANAGEMENT * man) { 
	int i ,sum=0 ;
	for (i = 0 ; i< man->frees; i++){ 
		sum +=man->freem[i].size ;
	}
	return sum ;
}
unsigned int memman_alloc (MEMORY_MANAGEMENT * man ,unsigned int size ) { 
	unsigned int i ,addr; 
	for (i = 0 ; i < man->frees ; i++){ 
		if (man->freem[i].size >= size ){  //可分配
			addr = man->freem[i].addr ;
			man->freem[i].addr +=size ; 
			man->freem[i].size -= size ;
			if (man->freem[i].size ==0){  //freem[i] 大小刚好分配完
				for ( i=i +1; i<man->frees ;i++){ 
					man->freem[i-1] = man->freem[i] ;
				}
				man->frees -- ;
			}
			return addr ;
		}
	}
	return 0 ; /*没有可用的空间*/
}

int memman_free (MEMORY_MANAGEMENT * man ,unsigned int addr ,unsigned int size ) { 
	int i  ,j;
	for (i = 0 ; i< man->frees ;i++){ 
		if(man->freem[i].addr >addr ) { 
			break ;
		}
		//此时 freem[i-1] <addr < freem[i]
		if (i ==0){  //frees =0 ,或第一个就匹配上
			if (man->frees != 0) {  //第一个就匹配上,只能是向右合并或不合并
				if (addr + size ==man->freem[i].addr) {  //此时向右合并
					man->freem[i].addr = addr ; 
					man->freem[i].size +=size ;
					return 0 ;
				}
				else {  //不合并
					if (man->frees >= MEMORY_FREE_SUB_SIZE) {  //freem空间不足.free失败
						man->losts ++ ;
						man->lostsize +=size ;
						return -1 ;
					}
					for (j = man->frees-1 ;j>=i;j-- ){ //从i(0)位置开始向右移动
						man->freem[j+1] =man->freem[j] ; 
					}
					man->freem[i].addr = addr ; 
					man->freem[i].size =size ;
					man->frees ++ ;
					return 0 ;
				}
			}
		}
		else if (i >0) {  //分为向左合并 ，向右合并 ，左右都合并 ，左右都不合并4种情况
			if(man->freem[i-1].addr +man->freem[i-1].size ==addr) { //向左合并
				if (addr +size ==man->freem[i].addr) { ////也能向右合并 
					for (j = i+1; j<=man->frees-1 ;j++) { 
						man->freem[j-1] =man->freem[j] ; 
					}
					man->frees --;
				} 
				else { //不能向右合并，只能向左 
					man->freem[i-1].size +=size ;
				} 
				return 0 ;
			}
			else { //左右都不合并
				if (man->frees >= MEMORY_FREE_SUB_SIZE) {  //freem空间不足.free失败
						man->losts ++ ;
						man->lostsize +=size ;
						return -1 ;
				}
				for (j = man->frees-1 ;j>=i;j-- ){ //从i(0)位置开始向右移动
						man->freem[j+1] =man->freem[j] ; 
				}
				man->frees ++ ;
				man->freem[i].addr = addr ; 
				man->freem[i].size =size ;
				return 0 ;
			}
		}
	}
}


unsigned int memman_alloc_4k (MEMORY_MANAGEMENT * man ,unsigned int size ){ 
	size =  (size +0xfff) &0xfffff000 ; 
	return  memman_alloc(man ,size );
}

int memman_free_4k (MEMORY_MANAGEMENT * man ,unsigned int addr ,unsigned int size ) { 
	size =  (size +0xfff) &0xfffff000 ; 
	return memman_free(man ,addr,size) ;
}  
  